package cn.com.lms.business.core.quartz;

import cn.com.lms.business.core.util.FBUtils;
import com.bnzj.cloud.business.core.persistence.entity.SysJobLog;
import com.bnzj.cloud.business.core.service.SysJobLogService;
import com.bnzj.cloud.business.core.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author barry
 * @see org.springframework.scheduling.quartz.QuartzJobBean
 */
@Slf4j
public abstract class BaseQuartzJob implements Job {

    @Resource
    protected SysJobLogService sysJobLogService;

    @Resource
    protected SysUserService sysUserService;

    protected boolean enabledLog;

    protected BaseQuartzJob(boolean enabledLog) {
        this.enabledLog = enabledLog;
    }

    /**
     * This implementation applies the passed-in job data map as bean property
     * values, and delegates to {@code executeInternal} afterwards.
     *
     * @see #executeInternal
     */
    @Override
    public final void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            MutablePropertyValues pvs = new MutablePropertyValues();
            pvs.addPropertyValues(context.getScheduler().getContext());
            pvs.addPropertyValues(context.getMergedJobDataMap());
            bw.setPropertyValues(pvs, true);
        } catch (SchedulerException e) {
            throw new JobExecutionException(e);
        }
        SysJobLog sysJobLog = new SysJobLog();
        long startTime = System.currentTimeMillis();
        try {
            executeInternal(context);
        } catch (Exception e) {//e.printStackTrace();
            if (enabledLog) {
                sysJobLog.setFlag(false);
                sysJobLog.setRemark(e.getMessage());
            }
            if (e instanceof JobExecutionException) {
                throw e;
            }
            throw new JobExecutionException(e);
        } finally {
            long endTime = System.currentTimeMillis();
            if (enabledLog) {
                sysJobLog.setName(context.getJobDetail().getKey().getName());// 获得任务名称
                sysJobLog.setDescription(context.getJobDetail().getDescription());
                //String triggerName = "manualTrigger";//手动执行
                sysJobLog.setTriggerName(context.getTrigger().getKey().getName());
                sysJobLog.setFlag(true);
                sysJobLog.setRemark("SUCCESS");
                float runTime = (float) (endTime - startTime) / 1000;
                sysJobLog.setRunTime(runTime);
                sysJobLog.setStartTime(new Date(startTime));
                sysJobLog.setEndTime(new Date(endTime));
                log.info("执行Job：{}---{}---{}", sysJobLog.getTriggerName(), sysJobLog.getName(), sysJobLog.getDescription());
                SysJobLog jobLog = FBUtils.saveBefore(sysJobLog, sysUserService.getAdmin());
                sysJobLogService.save(jobLog);
            }
        }
    }

    /**
     * Execute the actual job. The job data map will already have been
     * applied as bean property values by execute. The contract is
     * exactly the same as for the standard Quartz execute method.
     *
     * @see #execute
     */
    protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException;

    public boolean isEnabledLog() {
        return enabledLog;
    }

    public void setEnabledLog(boolean enabledLog) {
        this.enabledLog = enabledLog;
    }
}
